﻿using System;
using System.Windows.Input;
using YWM.Dto;

namespace PLCWpfTest.Common
{
    public abstract class BaseCommand : EmptyDto, ICommand
    {
        public event EventHandler CanExecuteChanged
        {
            add { CommandManager.RequerySuggested += value; }
            remove { CommandManager.RequerySuggested -= value; }
        }

        private event Func<object, bool> _beforeCanExecute;
        public event Func<object, bool> BeforeCanExecute
        {
            add { _beforeCanExecute += value; }
            remove { _beforeCanExecute -= value; }
        }

        private event Func<object, bool> _beforeExecute;
        public event Func<object, bool> BeforeExecute
        {
            add { _beforeExecute += value; }
            remove { _beforeExecute -= value; }
        }

        private bool _isExecuting;
        public bool IsExecuting
        {
            get
            {
                return _isExecuting;
            }
            set
            {
                SetProperty(ref _isExecuting, value);
                RaiseCanExecuteChanged();
            }
        }

        protected void RaiseCanExecuteChanged()
        {
            CommandManager.InvalidateRequerySuggested();
        }

        public bool CanExecute(object parameter)
        {
            if (_beforeCanExecute != null)
            {
                if (!_beforeCanExecute(parameter))
                {
                    return false;
                }
            }
            return OnCanExecute(parameter);
        }

        protected virtual bool OnCanExecute(object parameter)
        {
            return !IsExecuting;
        }

        public void Execute(object parameter)
        {
            if (CanExecute(parameter))
            {
                if (_beforeExecute?.Invoke(parameter) == false)
                {
                    return;
                }
                OnExecute(parameter);
            }
        }

        protected abstract void OnExecute(object parameter);
    }
}